home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Visual Cafe 3
/
Visual Cafe 3.ISO
/
Vcafe
/
JFC.bin
/
DefaultFocusManager.java
< prev
next >
Wrap
Text File
|
1998-06-30
|
12KB
|
324 lines
/*
* @(#)DefaultFocusManager.java 1.7 98/03/11
*
* Copyright (c) 1997 Sun Microsystems, Inc. All Rights Reserved.
*
* This software is the confidential and proprietary information of Sun
* Microsystems, Inc. ("Confidential Information"). You shall not
* disclose such Confidential Information and shall use it only in
* accordance with the terms of the license agreement you entered into
* with Sun.
*
* SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
* SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
* IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
* PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES
* SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
* THIS SOFTWARE OR ITS DERIVATIVES.
*
*/
package com.sun.java.swing;
/**
* Default swing focus manager implementation
*
* @version 1.7 03/11/98
* @author Arnaud Weber
*/
import java.awt.event.KeyEvent;
import java.awt.Component;
import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.Window;
import java.awt.Dialog;
import java.awt.Rectangle;
import java.util.Vector;
public class DefaultFocusManager extends FocusManager {
/** This method is called by JComponents when a key event occurs.
* JComponent gives key events to the focus manager
* first, then to key listeners, then to the keyboard UI dispatcher.
* This method should look at the key event and change the focused
* component if the key event matches the receiver's focus manager
* hot keys. For example the default focus manager will change the
* focus if the key event matches TAB or Shift + TAB.
* The focus manager should call consume() on <b>anEvent</b> if
* <code>anEvent</code> has been processed.
* <code>focusedComponent</code> is the component that currently has
* the focus.
* Note: FocusManager will receive KEY_PRESSED, KEY_RELEASED and KEY_TYPED
* key events. If one event is consumed, all other events type should be consumed.
*/
public void processKeyEvent(Component focusedComponent,KeyEvent anEvent) {
if(anEvent.getKeyCode() == KeyEvent.VK_TAB || anEvent.getKeyChar() == '\t') {
/** If the focused component manages focus, let it do so
* if control is not pressed
*/
if(focusedComponent instanceof JComponent) {
JComponent fc = (JComponent) focusedComponent;
if(fc.isManagingFocus()) {
if(!((anEvent.getModifiers() & ActionEvent.CTRL_MASK) ==
ActionEvent.CTRL_MASK))
return;
}
}
/** If this is not a key press, consume and return **/
if(anEvent.getID() != KeyEvent.KEY_PRESSED){
anEvent.consume();
return;
}
if((anEvent.getModifiers() & ActionEvent.SHIFT_MASK) == ActionEvent.SHIFT_MASK)
focusPreviousComponent(focusedComponent);
else
focusNextComponent(focusedComponent);
anEvent.consume();
}
}
/** Cause the focus manager to set the focus on the next focusable component **/
public void focusNextComponent(Component aComponent) {
if(aComponent instanceof JComponent) {
JComponent fc = (JComponent) aComponent;
Component nc;
Container root = getFocusRoot(fc);
if(root != null) {
nc = getFocusableComponentAfter(fc,root,true);
if(nc != null) {
if(nc instanceof JComponent)
((JComponent)nc).grabFocus();
else
nc.requestFocus();
}
}
}
}
/** Cause the focus manager to set the focus on the previous focusable component **/
public void focusPreviousComponent(Component aComponent) {
if(aComponent instanceof JComponent) {
JComponent fc = (JComponent) aComponent;
Component nc;
Container root = getFocusRoot(fc);
if(root != null) {
nc = getFocusableComponentAfter(fc,root,false);
if(nc != null) {
if(nc instanceof JComponent)
((JComponent)nc).grabFocus();
else
nc.requestFocus();
}
}
}
}
Container getFocusRoot(Component c) {
Container p;
for(p = c.getParent() ; p != null ; p = p.getParent()) {
if(((p instanceof JComponent) && ((JComponent)p).isFocusCycleRoot()) ||
(p instanceof Window) || (p instanceof Dialog))
return p;
}
return null;
}
private Component getFocusableComponentAfter(Component focusedComponent,
Container rootContainer,
boolean moveForward) {
Component nextComponent;
Component initialComponent;
nextComponent = initialComponent = focusedComponent;
do {
if(moveForward)
nextComponent = getNextComponent(nextComponent,rootContainer,true);
else
nextComponent = getPreviousComponent(nextComponent,rootContainer);
if(nextComponent == null)
break;
if(nextComponent == initialComponent)
break;
} while(!(nextComponent.isVisible() &&
nextComponent.isFocusTraversable() &&
nextComponent.isEnabled()));
return nextComponent;
}
private Component getNextComponent(Component component,
Container root,
boolean canGoDown) {
Component nsv = null;
if(canGoDown && component.isVisible() &&
(((component instanceof JComponent) &&
!((JComponent)component).isManagingFocus()) ||
!(component instanceof JComponent)) &&
((component instanceof Container) && ((Container)component).getComponentCount() > 0)) {
return getFirstComponent((Container)component);
} else {
Container parent = component.getParent();
nsv = getComponentAfter(parent,component);
if(nsv != null)
return nsv;
if(parent == root)
return root;
else
return getNextComponent(parent,root,false);
}
}
private Component getPreviousComponent(Component component,Container root) {
Container parent = component.getParent();
if(component == root)
return getDeepestLastComponent(root);
else {
Component nsv = getComponentBefore(parent,component);
if(nsv != null)
return getDeepestLastComponent(nsv);
else
return parent;
}
}
private Component getDeepestLastComponent(Component component) {
if(component.isVisible() &&
(((component instanceof JComponent) &&
!((JComponent)component).isManagingFocus()) ||
!(component instanceof JComponent)) &&
((component instanceof Container) && ((Container)component).getComponentCount() > 0)) {
return getDeepestLastComponent(getLastComponent((Container) component));
} else
return component;
}
/** Return the first component that should receive the focus **/
public Component getFirstComponent(Container aContainer) {
Component orderedChildren[] = childrenTabOrder(aContainer);
if(orderedChildren.length > 0)
return orderedChildren[0];
else
return null;
}
/** Return the last component that should receive the focus **/
public Component getLastComponent(Container aContainer) {
Component orderedChildren[] = childrenTabOrder(aContainer);
if(orderedChildren.length > 0)
return orderedChildren[orderedChildren.length - 1];
else
return null;
}
/** Return the component that should receive the focus before aComponent **/
public Component getComponentBefore(Container aContainer,Component aComponent) {
Component orderedChildren[] = childrenTabOrder(aContainer);
int i,c;
for(i=1,c=orderedChildren.length ; i < c ; i++)
if(orderedChildren[i] == aComponent)
return orderedChildren[i-1];
return null;
}
/** Return the component the should receive the focus after aComponent **/
public Component getComponentAfter(Container aContainer,Component aComponent) {
Component orderedChildren[] = childrenTabOrder(aContainer);
int i,c;
for(i=0,c=orderedChildren.length - 1; i < c ; i++)
if(orderedChildren[i] == aComponent)
return orderedChildren[i+1];
return null;
}
/** Return true if <code>a</code> should be before <code>b</code> in the
* "tab" order. Override this method if you want to change the automatic
* "tab" order.
* The default implementation will order tab to give a left to right, top
* down order. Override this method if another order is required.
*/
public boolean compareTabOrder(Component a,Component b) {
Rectangle bounds;
int ay,by;
int ax,bx;
if(a instanceof JComponent) {
ay = ((JComponent)a).getY();
ax = ((JComponent)a).getX();
} else {
bounds = a.getBounds();
ay = bounds.y;
ax = bounds.x;
}
if(b instanceof JComponent) {
by = ((JComponent)b).getY();
bx = ((JComponent)b).getX();
} else {
bounds = b.getBounds();
by = bounds.y;
bx = bounds.x;
}
if(Math.abs(ay - by) < 10) {
return (ax < bx);
}
return (ay < by);
}
Component[] childrenTabOrder(Container co) {
Component children[] = co.getComponents();
Component tmp;
int i,j,c;
boolean hasLink = false;
/** Get the tab order from the geometry **/
for(i=0,c = children.length ; i < c ; i++) {
if(!hasLink && (children[i] instanceof JComponent) &&
((JComponent)children[i]).getNextFocusableComponent() != null)
hasLink = true;
for(j=i ; j < c ; j++) {
if(i==j)
continue;
if(compareTabOrder(children[j],children[i])) {
tmp = children[i];
children[i] = children[j];
children[j] = tmp;
}
}
}
if(hasLink) {
int index;
Component nextComponent;
Vector v = new Vector(c);
for(i=0; i < c ; i++)
v.addElement(children[i]);
/** Take in account the next component link **/
for(i=0 ; i < c ; i++) {
if((children[i] instanceof JComponent) &&
(nextComponent = ((JComponent)children[i]).getNextFocusableComponent()) != null) {
if((index = v.indexOf(nextComponent)) != -1) {
v.removeElementAt(index);
v.insertElementAt(nextComponent,i+1);
}
}
}
for(i=0 ; i < c ; i++)
children[i] = (Component) v.elementAt(i);
}
return children;
}
}